/*
 * Copyright (C) 2005 - 2013 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008 - 2013 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2006 - 2013 ScriptDev2 <http://www.scriptdev2.com/>
 *
 * Copyright (C) 2010 - 2013 ProjectSkyfire <http://www.projectskyfire.org/>
 *
 * Copyright (C) 2011 - 2013 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "ScriptPCH.h"
#include "blackfathom_deeps.h"
#include "ScriptedEscortAI.h"

enum eSpells {
    SPELL_BLESSING_OF_BLACKFATHOM = 8733,
    SPELL_RAVAGE = 8391,
    SPELL_FROST_NOVA = 865,
    SPELL_FROST_BOLT_VOLLEY = 8398,
    SPELL_TELEPORT_DARNASSUS = 9268
};

#define GOSSIP_ITEM_MORRIDUNE "Please port me to Darnassus"

const Position HomePosition = { -815.817f, -145.299f, -25.870f, 0 };

class go_blackfathom_altar: public GameObjectScript {
public:
    go_blackfathom_altar() :
            GameObjectScript("go_blackfathom_altar") {
    }

    bool OnGossipHello(Player *pPlayer, GameObject* /*pGo*/) {
        if (!pPlayer->HasAura(SPELL_BLESSING_OF_BLACKFATHOM))
            pPlayer->AddAura(SPELL_BLESSING_OF_BLACKFATHOM, pPlayer);
        return true;
    }
};

class go_blackfathom_fire: public GameObjectScript {
public:
    go_blackfathom_fire() :
            GameObjectScript("go_blackfathom_fire") {
    }

    bool OnGossipHello(Player * /*pPlayer*/, GameObject* pGo) {
        InstanceScript *pInstance = pGo->GetInstanceScript();

        if (pInstance) {
            pGo->SetGoState(GO_STATE_ACTIVE);
            pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
            pInstance->SetData(DATA_FIRE, pInstance->GetData(DATA_FIRE) + 1);
            return true;
        }
        return false;
    }
};

class npc_blackfathom_deeps_event: public CreatureScript {
public:
    npc_blackfathom_deeps_event() :
            CreatureScript("npc_blackfathom_deeps_event") {
    }

    CreatureAI* GetAI(Creature* pCreature) const {
        return new npc_blackfathom_deeps_eventAI(pCreature);
    }

    struct npc_blackfathom_deeps_eventAI: public ScriptedAI {
        npc_blackfathom_deeps_eventAI(Creature* pCreature) :
                ScriptedAI(pCreature) {
            if (pCreature->isSummon()) {
                pCreature->SetHomePosition(HomePosition);
                AttackPlayer();
            }

            pInstance = pCreature->GetInstanceScript();
        }

        InstanceScript* pInstance;

        uint32 uiRavageTimer;
        uint32 uiFrostNovaTimer;
        uint32 uiFrostBoltVolleyTimer;

        bool bFlee;

        void Reset() {
            bFlee = false;

            uiRavageTimer = urand(5000, 8000);
            uiFrostNovaTimer = urand(9000, 12000);
            uiFrostBoltVolleyTimer = urand(2000, 4000);
        }

        void AttackPlayer() {
            Map::PlayerList const &PlList = me->GetMap()->GetPlayers();

            if (PlList.isEmpty())
                return;

            for (Map::PlayerList::const_iterator i = PlList.begin();
                    i != PlList.end(); ++i) {
                if (Player* pPlayer = i->getSource()) {
                    if (pPlayer->isGameMaster())
                        continue;

                    if (pPlayer->isAlive()) {
                        me->SetInCombatWith(pPlayer);
                        pPlayer->SetInCombatWith(me);
                        me->AddThreat(pPlayer, 0.0f);
                    }
                }
            }
        }

        void UpdateAI(const uint32 uiDiff) {
            if (!UpdateVictim())
                return;

            switch (me->GetEntry()) {
            case NPC_AKU_MAI_SNAPJAW: {
                if (uiRavageTimer <= uiDiff) {
                    DoCast(me->getVictim(), SPELL_RAVAGE);
                    uiRavageTimer = urand(9000, 14000);
                } else
                    uiRavageTimer -= uiDiff;
                break;
            }
            case NPC_MURKSHALLOW_SOFTSHELL:
            case NPC_BARBED_CRUSTACEAN: {
                if (!bFlee && HealthBelowPct(15)) {
                    bFlee = true;
                    me->DoFleeToGetAssistance();
                }
                break;
            }
            case NPC_AKU_MAI_SERVANT: {
                if (uiFrostBoltVolleyTimer <= uiDiff) {
                    if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) {
                        if (pTarget)
                            DoCast(pTarget, SPELL_FROST_BOLT_VOLLEY);
                    }
                    uiFrostBoltVolleyTimer = urand(5000, 8000);
                } else
                    uiFrostBoltVolleyTimer -= uiDiff;
                if (uiFrostNovaTimer <= uiDiff) {
                    DoCastAOE(SPELL_FROST_NOVA, false);
                    uiFrostNovaTimer = urand(25000, 30000);
                } else
                    uiFrostNovaTimer -= uiDiff;
                break;
            }
            }

            DoMeleeAttackIfReady();
        }

        void JustDied(Unit* /*pKiller*/) {
            if (me->isSummon()) //we are not a normal spawn.
                if (pInstance)
                    pInstance->SetData(DATA_EVENT,
                            pInstance->GetData(DATA_EVENT) + 1);
        }
    };
};

enum eMorridune {
    SAY_MORRIDUNE_1 = -1048003, SAY_MORRIDUNE_2 = -1048004
};

class npc_morridune: public CreatureScript {
public:
    npc_morridune() :
            CreatureScript("npc_morridune") {
    }

    bool OnGossipSelect(Player* pPlayer, Creature* /*pCreature*/,
            uint32 /*uiSender*/, uint32 uiAction) {
        pPlayer->PlayerTalkClass->ClearMenus();
        switch (uiAction) {
        case GOSSIP_ACTION_INFO_DEF + 1:
            pPlayer->TeleportTo(1, 9952.239f, 2284.277f, 1341.394f, 1.595f);
            pPlayer->CLOSE_GOSSIP_MENU();
            break;
        }
        return true;
    }

    bool OnGossipHello(Player* pPlayer, Creature* pCreature) {
        pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MORRIDUNE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);

        pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
        return true;
    }

    CreatureAI* GetAI(Creature* pCreature) const {
        return new npc_morriduneAI(pCreature);
    }

    struct npc_morriduneAI: public npc_escortAI {
        npc_morriduneAI(Creature* pCreature) :
                npc_escortAI(pCreature) {
            DoScriptText(SAY_MORRIDUNE_1, pCreature);
            me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
            Start(false, false, NULL);
        }

        void WaypointReached(uint32 uiPoint) {
            switch (uiPoint) {
            case 4:
                SetEscortPaused(true);
                me->SetOrientation(1.775791f);
                me->SendMovementFlagUpdate();
                me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                DoScriptText(SAY_MORRIDUNE_2, me);
                break;
            }
        }
    };
};

void AddSC_blackfathom_deeps() {
    new go_blackfathom_altar();
    new go_blackfathom_fire();
    new npc_blackfathom_deeps_event();
    new npc_morridune();
}
